package com.kehutong.house.admin;

import com.kehutong.admin.entity.Corp;
import com.kehutong.common.DoveClient;
import com.kehutong.common.ExcelUtil;
import com.kehutong.common.permission.DataPermissionQuery;
import com.kehutong.common.permission.PermissionNameDto;
import com.kehutong.common.util.Token;
import com.kehutong.house.constant.SupplierConstant;
import com.kehutong.house.entity.*;
import com.kehutong.house.enums.AccessControlStatus;
import com.kehutong.house.enums.AccessControlType;
import com.kehutong.house.enums.DeviceManagementType;
import com.kehutong.house.service.HouseService;
import com.kehutong.house.util.DateUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.coraframework.inject.Inject;
import org.coraframework.json.JSONArray;
import org.coraframework.json.JSONObject;
import org.coraframework.mvc.MvcAction;
import org.coraframework.mvc.http.Bean;
import org.coraframework.mvc.http.ReqMapping;
import org.coraframework.mvc.http.result.Result;
import org.coraframework.orm.jdbc.JdbcSession;
import org.coraframework.orm.jdbc.Page;
import org.coraframework.orm.jdbc.connection.ThreadLocalCache;
import org.coraframework.orm.jdbc.execute.entity.FindPage;
import org.coraframework.util.Objects;
import org.coraframework.util.UUIDGenerator;
import org.coraframework.logger.Logger;
import org.coraframework.logger.LoggerFactory;
import java.io.File;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * TODO 门禁授权
 *
 * @author zwp
 * @version 1.0
 * @date 2021/7/06 14:41
 */
@MvcAction
@ReqMapping("/admin/basic/access")
public class AccessController {
    @Inject
    private JdbcSession jdbcSession;
    @Inject
    private HouseService houseService;
    @Inject
    private DoveClient doveClient;
    private Logger log= LoggerFactory.getLogger(AccessController.class);
    /**
     * 获取所有的门禁类型
     * @return
     */
    @ReqMapping("/listAccessControlType")
    public Object listAccessControlType() {
        JSONArray jsonArray=new JSONArray();
        AccessControlType[] accessControlTypes = AccessControlType.values();
        for (AccessControlType accessControlType : accessControlTypes) {
            JSONObject jsonObject=new JSONObject();
            jsonObject.put("id",accessControlType.getId());
            jsonObject.put("desc",accessControlType.getDesc());
            jsonArray.add(jsonObject);
        }
        return jsonArray;
    }
    /**
     * 获取所有的门禁类型
     * @return
     */
    @ReqMapping("/listAuthStatus")
    public Object listAuthStatus() {
        JSONArray jsonArray=new JSONArray();
        AccessControlStatus[] accessControlStatusArr = AccessControlStatus.values();
        for (AccessControlStatus accessControlStatus : accessControlStatusArr) {
            JSONObject jsonObject=new JSONObject();
            jsonObject.put("id",accessControlStatus.getId());
            jsonObject.put("desc",accessControlStatus.getDesc());
            jsonArray.add(jsonObject);
        }
        return jsonArray;
    }
    @Bean(newInstance=true, copy=true)
    @ReqMapping("/accessControlAuth")
    public Object accessControlAuth(Token token,AccessControlAuth accessControlAuth) {
        try {
            String corpId=token.getCompanyNo();   //企业id
            if(Objects.isEmpty(accessControlAuth.getDeviceId())||Objects.isEmpty(accessControlAuth.getHouseIds())||Objects.isEmpty(accessControlAuth.getAccessControlTypeIds())||Objects.isEmpty(accessControlAuth.getResidentIds())){
                return Result.badArgument();
            }else{
                String otType="1";// 1增加授权、2更新授权、3撤销授权
                DeviceManagement deviceManagement=jdbcSession.findById(DeviceManagement.class,accessControlAuth.getDeviceId());
                SupplierConfig supplierConfig=jdbcSession.findOne(SupplierConfig.class).eq("supplierId",deviceManagement.getSupplierId()).exe();
                if(supplierConfig==null){
                    return Result.error(0, "请配置设备供应商");
                }
                String method="grantRights";
                String url=supplierConfig.getServiceUrl()+method; //接口请求地址
                String finalOtType = otType;
                for(String residentId:accessControlAuth.getResidentIds()){
                    long virtualCard=SupplierConstant.VIRTUAL_CARD;
                    List<AccessControlAuth>accessControlAuthList=jdbcSession.findArray(AccessControlAuth.class).order("virtualCard","desc").exe();
                    if(Objects.nonEmpty(accessControlAuthList)) {
                        virtualCard = Long.valueOf(accessControlAuthList.get(0).getVirtualCard()) + 1;
                    }
                    Resident resident=jdbcSession.findOne(Resident.class).eq("id",residentId).exe();
                    AccessControlAuth accessControlAuthTemp=jdbcSession.findOne(AccessControlAuth.class)
                            .eq("deleted",false)
                            .eq("deviceId",accessControlAuth.getDeviceId())
                            .eq("residentId",residentId)
                            .noEq("authStatus",AccessControlStatus.INVALID.getId())
                            .exe();
                    long finalVirtualCard = virtualCard;
                    JSONObject result = doveClient.post(url, http->{
                        JSONObject body = new JSONObject();
                        body.put("opType", finalOtType);
                        body.put("areaId",corpId);
                        body.put("doorSeq", deviceManagement.getDeviceSeq());
                        body.put("cardSeq", String.valueOf(finalVirtualCard));
                        body.put("personId", residentId);
                        body.put("dueTime",DateUtils.timestampToStr(accessControlAuth.getDueTime(),DateUtils.PATTERN_2));
                        body.put("doorType","1");
                        body.put("ext",supplierConfig.getExt());
                        http.setBody(body.toString());
                    });
                    if(result!=null&&result.getIntValue("code")==200) {  //接口调用成功
                        JSONObject dataJson = result.getJSONObject("data");
                        String errcode = dataJson.getString("errcode");
                        log.info(dataJson.toJSONString());
                        if("0".equals(errcode)){
//                            if(accessControlAuthTemp!=null){
//                                if(AccessControlStatus.INVALID.getId().equals(accessControlAuthTemp.getAuthStatus()))
//                                accessControlAuthTemp.setResidentName(resident.getRealname());
//                                accessControlAuthTemp.setDeviceId(accessControlAuth.getDeviceId());
//                                accessControlAuthTemp.setResidentId(residentId);
//                                accessControlAuthTemp.setHouseIds(accessControlAuth.getHouseIds());
//                                accessControlAuthTemp.setAccessControlTypeIds(accessControlAuth.getAccessControlTypeIds());
//                                accessControlAuthTemp.setDueTime(accessControlAuth.getDueTime());
//                                accessControlAuthTemp.setAuthStatus(AccessControlStatus.IN_FORCE.getId());
//                                jdbcSession.updateById(accessControlAuthTemp);
//                            }else{
                            if(accessControlAuthTemp==null){
                                accessControlAuthTemp=new AccessControlAuth(UUIDGenerator.randomUUID());
                                accessControlAuthTemp.setResidentName(resident.getRealname());
                                accessControlAuthTemp.setDeviceId(accessControlAuth.getDeviceId());
                                accessControlAuthTemp.setResidentId(residentId);
                                accessControlAuthTemp.setHouseIds(accessControlAuth.getHouseIds());
                                accessControlAuthTemp.setAccessControlTypeIds(accessControlAuth.getAccessControlTypeIds());
                                accessControlAuthTemp.setVirtualCard(String.valueOf(finalVirtualCard));
                                accessControlAuthTemp.setDueTime(accessControlAuth.getDueTime());
                                accessControlAuthTemp.setAuthStatus(AccessControlStatus.IN_FORCE.getId());
                                jdbcSession.insert(accessControlAuthTemp);
                            }
                            virtualCard++;
                        }else{
                            log.info("门禁编号:"+virtualCard+"用户姓名:"+resident.getRealname()+"的门禁权限下发到设备接口返回"+dataJson.getString("msg"));
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("用户权限下发到设备发生异常"+e.getMessage(),e);
        }
        return Result.success();
    }
    @Bean(newInstance=true, copy=true)
    @ReqMapping("/authCard")
    public Object authCard(AccessControlAuth accessControlAuth,Token token){
        JSONObject msgJson=new JSONObject();//返回给前端
        try {
            String corpId=token.getCompanyNo();   //企业id
            AccessControlAuth accessControlAuthTemp=jdbcSession.findById(AccessControlAuth.class,accessControlAuth.getId());
            if(accessControlAuthTemp==null){
                return Result.error(0, "用户门禁不存在");
            }
            Timestamp dueTime=accessControlAuth.getDueTime();
            DeviceManagement deviceManagement=jdbcSession.findById(DeviceManagement.class,accessControlAuth.getDeviceId());
            SupplierConfig supplierConfig=jdbcSession.findOne(SupplierConfig.class).eq("supplierId",deviceManagement.getSupplierId()).exe();
            if(supplierConfig==null){
                return Result.error(0, "请配置设备供应商");
            }
            String method="grantRights";
            String url=supplierConfig.getServiceUrl()+method; //接口请求地址
            Timestamp finalDueTime = dueTime;
            JSONObject result = doveClient.post(url, http->{
                JSONObject body = new JSONObject();
                body.put("opType", accessControlAuth.getOpType());
                body.put("areaId",corpId);
                body.put("doorSeq", deviceManagement.getDeviceSeq());
                body.put("cardSeq", accessControlAuth.getCardSeq()==null?accessControlAuth.getVirtualCard():accessControlAuth.getCardSeq());
                body.put("personId", accessControlAuth.getResidentId());
                body.put("dueTime",DateUtils.timestampToStr(finalDueTime,DateUtils.PATTERN_2));
                body.put("doorType","1");
                body.put("ext",supplierConfig.getExt());
                http.setBody(body.toString());
            });
            if(result.getIntValue("code")==200) {  //接口调用成功
                JSONObject dataJson = result.getJSONObject("data");
                String errcode = dataJson.getString("errcode");
                log.info(dataJson.toJSONString());
                if ("0".equals(errcode)) {
                    accessControlAuthTemp.setCardSeq(accessControlAuth.getCardSeq());
                    accessControlAuthTemp.setDueTime(dueTime);
                    accessControlAuthTemp.setAuthStatus(accessControlAuth.getAuthStatus());
                    jdbcSession.updateById(accessControlAuthTemp);
                }else{
                    String msg=dataJson.getString("msg");  //接口返回的错误
                    msgJson.put("msg",msg);
                    log.info("门禁编号:" + accessControlAuth.getVirtualCard() + "用户姓名:" + accessControlAuth.getResidentName() + "的门禁权限下发到设备接口返回" + msg);
                    return Result.success(msg,msgJson);
                }
            }
        } catch (Exception e) {
            log.error("用户权限下发到设备发生异常"+e.getMessage(),e);
        }
        return Result.success();
    }
    @ReqMapping("/list")
    public Page<AccessControlAuth> list(JSONObject jsonObject) throws Exception {
        FindPage<AccessControlAuth> findPage = jdbcSession.findPage(AccessControlAuth.class);
        findPage.eq("deleted",false);
        String typeId=jsonObject.getString("accessControlTypeId");
        String authStatus=jsonObject.getString("authStatus");
        String houseId=jsonObject.getString("houseId");
        String deviceId=jsonObject.getString("deviceId");
        String residentName=jsonObject.getString("residentName");
        if(Objects.nonEmpty(deviceId)){
            findPage.like("deviceId",deviceId);
        }
        if(Objects.nonEmpty(typeId)){
            findPage.like("accessControlTypeIds",typeId);
        }
        if(Objects.nonEmpty(authStatus)){
            findPage.eq("authStatus",authStatus);
        }
        if(Objects.nonEmpty(houseId)){
            findPage.eq("houseId",houseId);
        }
        if(Objects.nonEmpty(residentName)){
            findPage.eq("residentName",residentName);
        }
        findPage.order("createTime","desc").order("virtualCard", "DESC");;
        findPage.page(jsonObject);
//        PermissionNameDto dto = new PermissionNameDto();
//        dto.setManageDepartmentNo("departmentNo");
//        DataPermissionQuery.setManageDataSql(findPage, dto, null);
        Page<AccessControlAuth> page = findPage.exe();
        page.getList().forEach(item -> {
            //查询用户
            Resident resident=jdbcSession.findOne(Resident.class).eq("id",item.getResidentId()).exe();
            item.setResidentName(resident.getRealname());
            //查询房屋
            House house=jdbcSession.findById(House.class,item.getHouseIds().get(2));
            //封装开通的门禁类型
            StringBuilder accessControlTypeDescs=new StringBuilder();
            for(String accessControlTypeId:item.getAccessControlTypeIds()){
                accessControlTypeDescs.append(AccessControlType.get(accessControlTypeId).getDesc()).append(",");
            }
            if(accessControlTypeDescs.length()>0){
                accessControlTypeDescs.setLength(accessControlTypeDescs.length()-1);
            }
            item.setAccessControlTypeDescs(accessControlTypeDescs.toString()); //设置门禁类型
            //封装开通状态
            item.setAuthStatusName(AccessControlStatus.get(item.getAuthStatus()).getDesc());
            StringBuilder stringBuilder=new StringBuilder();
            stringBuilder.append(house.getCommunityName()).append("/").append(house.getBuildName())
                    .append(Objects.nonEmpty(house.getUnitName())?house.getUnitName():"").append("/").append(house.getFloorName())
                    .append(house.getName());
            item.setHouseName(stringBuilder.toString());
        });
        return page;
    }
    @ReqMapping("/update")
    public Object update(JSONObject jsonObject) {
        AccessControlAuth model=jdbcSession.findById(AccessControlAuth.class,jsonObject.getString("id"));
        String authStatus=jsonObject.getString("authStatus");
        if(AccessControlStatus.INVALID.getId().equals(authStatus)){ //回收
            model.setDueTime(null);
            model.setCardSeq(null);
        }
        model.setAuthStatus(authStatus);
        jdbcSession.updateById(model);
        return Result.success(model);
    }
    @ReqMapping("/delete")
    public Object delete(AccessControlAuth accessControlAuth) {
        AccessControlAuth model=jdbcSession.findById(AccessControlAuth.class,accessControlAuth.getId());
        model.setDeleted(true);
        jdbcSession.updateById(model);
        return Result.success(model);
    }
    @ReqMapping("/getAccessControlCount")
    public Page<Community> getAccessControlCount(JSONObject jsonObject){
        String id=jsonObject.getString("communityId");
        FindPage<Community> find=jdbcSession.findPage(Community.class);
        find.eq("deleted", false);
        if(Objects.nonEmpty(id)){
            find.eq("id",id);
        }
        find.page(jsonObject);
        Page<Community>page=find.exe();
        page.getList().forEach(item -> {
            List<DeviceManagement>deviceManagementList=jdbcSession.findArray(DeviceManagement.class)
                    .eq("deleted", false)
                    .eq("state",true)
                    .eq("bindingState", DeviceManagementType.BOUND.getId())
                    .eq("communityId",item.getId())
                    .exe();  //该小区的设备list
            item.setDeviceCount(deviceManagementList.size());  //总设备数
            for(DeviceManagement deviceManagement:deviceManagementList){
                String typeId=deviceManagement.getEquipmentType();
                if(item.getDeviceTypeCountMap().containsKey(typeId)){
                    int count=item.getDeviceTypeCountMap().get(typeId);
                    count++;
                    item.getDeviceTypeCountMap().put(typeId,count);
                }else{
                    item.getDeviceTypeCountMap().put(typeId,1);  //不存在
                }
            }

        });
        return page;


    }

    @ReqMapping("/exportAccessControlCountData")
    public Object exportAccessControlCountData(JSONObject jsonObject) throws Exception {
        jsonObject.put("pageNo", 1);
        jsonObject.put("pageSize", Short.MAX_VALUE);
        Page<Community> page = getAccessControlCount(jsonObject);
        File dataFile = exportFriendDataFile(page.getList());
        return com.kehutong.common.errcode.Result.download(dataFile);
    }
    private File exportFriendDataFile(List<Community> communityList) throws Exception {
        Workbook wb = exportSupplierWorkBook(communityList);
        return ExcelUtil.writeXlsFile(wb, "设备统计列表", ".xls");
    }
    private Workbook exportSupplierWorkBook(List<Community> communityList)throws Exception {
        // 生成模板文件
        HSSFWorkbook wb = new HSSFWorkbook();
        Sheet sheet = wb.createSheet();
        Row headerRow = sheet.createRow(0);
        int headerCellNum = 0;
        List<EquipmentClassify>equipmentClassifyList=getEquipmentClassify(); //获取设备类型
        List<String>chargeUserInstrumentList=new ArrayList<String>();
        chargeUserInstrumentList.add("项目/小区名称");
        chargeUserInstrumentList.add("总数");
        for(EquipmentClassify EquipmentClassify:equipmentClassifyList){
            chargeUserInstrumentList.add(EquipmentClassify.getDeviceClassifyName());
        }
        for (String s : chargeUserInstrumentList) {
            Cell cell = headerRow.createCell(headerCellNum++);
            cell.setCellValue(s);
        }
        int cellNum = 0;
        for (int i = 0; i < communityList.size(); i++) {
            Community community = communityList.get(i);
            Row row = sheet.createRow(i + 1);
            cellNum = 0;
            row.createCell(cellNum++).setCellValue(community.getName());
            row.createCell(cellNum++).setCellValue(community.getDeviceCount());
            for(EquipmentClassify EquipmentClassify:equipmentClassifyList){
                if(community.getDeviceTypeCountMap().containsKey(EquipmentClassify.getId())){
                    row.createCell(cellNum++).setCellValue(community.getDeviceTypeCountMap().get(EquipmentClassify.getId()));
                }else{
                    row.createCell(cellNum++).setCellValue(0);
                }
            }
        }

        // 自动列宽
        for (int i = 0; i < cellNum; i++) {
            if (i == 0) {
                // id列不调整
                continue;
            }
            // 自动列宽
            ExcelUtil.autoSizeColumn(sheet, i);
        }
        return wb;
    }

    /**
     * 查询所有设备类型
     * @return
     * @throws Exception
     */
    private List<EquipmentClassify> getEquipmentClassify() throws Exception {
        return jdbcSession.findArray(EquipmentClassify.class)
                .eq("deleted", false)
                .eq("typeStatus", true)
                .order("createTime", "DESC")
                .exe();
    }
    @ReqMapping("/getHouseCascaders")
    public Object getHouseCascaders() throws Exception{
        List<JSONObject> array = new ArrayList<JSONObject>();
        Map<String,List<JSONObject>>buildingMap=getBuildingMap();
        List<Community>communityList=jdbcSession.findArray(Community.class).eq("deleted",false).exe();
        communityList.forEach(item->{
            JSONObject communityJson=new JSONObject();
            communityJson.put("value",item.getId());
            communityJson.put("label",item.getName());
            communityJson.put("children", buildingMap.get(item.getId()));
            array.add(communityJson);
        });
        return array;
    }
    @ReqMapping("/getCommunityCascaders")
    public Object getCommunityCascaders(Token token) throws Exception{
        ArrayList<JSONObject> array = new ArrayList<JSONObject>();
        String corpId=token.getCompanyNo();   //企业id
        log.info("调用getCommunityCascaders,corpId========="+corpId);
        if(corpId!=null){
            JSONObject wyJson=new JSONObject();
            wyJson.put("value",corpId);
            wyJson.put("label",token.getCompanyName());
            wyJson.put("children", getCommunityByCorpId(corpId));
            array.add(wyJson);
        }else{
            List<Corp>corpList=jdbcSession.findArray(Corp.class).eq("deleted",false).exe();
            log.info("调用getCommunityCascaders,corpList.size()========="+corpList.size());
            corpList.forEach(item->{
                JSONObject wyJson=new JSONObject();
                wyJson.put("value",item.getId());
                wyJson.put("label",item.getName());
                wyJson.put("children",getCommunityByCorpId(item.getId()));
                array.add(wyJson);
            });
            ThreadLocalCache.current().setCorpId(null);
        }
        return array;
    }
    private List<JSONObject>getCommunityByCorpId(String corpId){
        log.info("调用getCommunityByCorpId，corpId="+corpId);
        List array=new ArrayList<JSONObject>();
        try {
            ThreadLocalCache.current().setCorpId(corpId);
            List<Community>communityList=jdbcSession.findArray(Community.class).eq("deleted",false).exe();
            communityList.forEach(item->{
                JSONObject jsonObject=new JSONObject();
                jsonObject.put("value",item.getId());
                jsonObject.put("label",item.getName());
                array.add(jsonObject);
            });
        } catch (Exception e) {
            log.error(e.getMessage(),e);
        }
        return array;
    }
    private Map<String,List<JSONObject>>getBuildingMap(){
        Map<String,List<JSONObject>>buildingMap=new HashMap<String,List<JSONObject>>();  //楼栋map
        Map<String,List<JSONObject>>houseMap=getHouseMap();
        List<Building>buildingList=jdbcSession.findArray(Building.class).eq("deleted",false).exe();
        buildingList.forEach(item->{
            List<JSONObject> array = null;
            if(buildingMap.containsKey(item.getCommunityNo())){
                array=buildingMap.get(item.getCommunityNo());
            }else{
                array=new ArrayList<JSONObject>();
                buildingMap.put(item.getCommunityNo(),array);
            }
            JSONObject jsonObject=new JSONObject();
            jsonObject.put("value",item.getId());
            jsonObject.put("label", Objects.nonEmpty(item.getUnitName()) ? item.getName() + "-" + item.getUnitName() : item.getName());
            jsonObject.put("children",houseMap.get(item.getId()));
            array.add(jsonObject);
        });
        return buildingMap;
    }
    private Map<String,List<JSONObject>>getHouseMap(){
        Map<String,List<JSONObject>>houseMap=new HashMap<String,List<JSONObject>>();  //房屋map
        List<House>houseList=jdbcSession.findArray(House.class).eq("deleted",false).exe();
        houseList.forEach(item->{
            List<JSONObject> array = null;
            if(houseMap.containsKey(item.getBuildNo())){
                array=houseMap.get(item.getBuildNo());
            }else{
                array=new ArrayList<JSONObject>();
                houseMap.put(item.getBuildNo(),array);
            }
            JSONObject jsonObject=new JSONObject();
            jsonObject.put("value",item.getId());
            jsonObject.put("label", item.getFloorName()+item.getName());
            array.add(jsonObject);
        });
        return houseMap;
    }
}
